using DocumentCreationSystem.Services;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;

namespace DocumentCreationSystem.Views
{
    public partial class DiagnosticsWindow : Window
    {
        private readonly ILogger<DiagnosticsWindow> _logger;
        private readonly AgentToolService _agentToolService;
        private bool _showSeverityText;
        private List<DiagRow> _allRows = new();
        private List<string> _allFiles = new(); // 保存完整文件路径（与 DiagRow.File 一致）

        public DiagnosticsWindow(IServiceProvider serviceProvider)
        {
            InitializeComponent();
            _logger = serviceProvider.GetRequiredService<ILogger<DiagnosticsWindow>>();
            _agentToolService = serviceProvider.GetRequiredService<AgentToolService>();

            Loaded += (_, __) => TryGuessProjectPath();
            // 默认显示 Severity 文本
            _showSeverityText = true;
        }

        private void TryGuessProjectPath()
        {
            try
            {
                var baseDir = AppContext.BaseDirectory;
                var probe = System.IO.Path.GetFullPath(System.IO.Path.Combine(baseDir, "..", "..", "..", "DocumentCreationSystem.csproj"));
                if (File.Exists(probe))
                {
                    ProjectPathText.Text = probe;
                }
            }
            catch { }
        }

        private async void RunDiagnostics_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                var projectPath = ProjectPathText.Text?.Trim();
                var severity = (SeverityFilter.SelectedItem as System.Windows.Controls.ComboBoxItem)?.Content?.ToString();

                var result = await _agentToolService.ExecuteToolAsync("get_diagnostics", projectPath ?? string.Empty);
                var rows = ParseDiagnosticsToRows(result);
                if (!string.IsNullOrEmpty(severity) && severity != "全部")
                {
                    rows = rows.Where(r => r.Severity.Equals(severity, StringComparison.OrdinalIgnoreCase)).ToList();
                }
                _allRows = rows;
                _allFiles = rows.Select(r => r.File).Distinct(StringComparer.OrdinalIgnoreCase).OrderBy(s => s, StringComparer.OrdinalIgnoreCase).ToList();
                RebuildFileFilterItems(rows);
                ApplyFilters();
            }
            catch (Exception ex)
            {
                MessageBox.Show($"运行诊断失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private List<DiagRow> ParseDiagnosticsToRows(string text)
        {
            var rows = new List<DiagRow>();
            using var reader = new StringReader(text);
            string? line;
            while ((line = reader.ReadLine()) != null)
            {
                // 形如：• [Warning] File.cs:12:34 ID123 信息...
                if (!line.StartsWith("• [")) continue;
                try
                {
                    var sevEnd = line.IndexOf(']');
                    var sev = line.Substring(3, sevEnd - 3);
                    var rest = line.Substring(sevEnd + 2);
                    var posSep = rest.IndexOf(' ');
                    var filePos = rest.Substring(0, posSep);
                    var idAndMsg = rest.Substring(posSep + 1);

                    var fileSep1 = filePos.LastIndexOf(':');
                    var fileSep0 = filePos.LastIndexOf(':', fileSep1 - 1);
                    var file = filePos.Substring(0, fileSep0);
                    var lineNo = int.Parse(filePos.Substring(fileSep0 + 1, fileSep1 - fileSep0 - 1));
                    var colNo = int.Parse(filePos.Substring(fileSep1 + 1));

                    var id = idAndMsg.Split(' ').FirstOrDefault() ?? "";
                    var msg = idAndMsg.Substring(id.Length).Trim();

                    rows.Add(new DiagRow
                    {
                        Severity = MapSeverityToChinese(sev),
                        Id = id,
                        Message = msg,
                        File = file,
                        Line = lineNo,
                        Column = colNo
                    });
                }
                catch { }
            }
            return rows;
        }

        private void BrowseProject_Click(object sender, RoutedEventArgs e)
        {
            var ofd = new OpenFileDialog
            {
                Title = "选择项目文件",
                Filter = "C# Project (*.csproj)|*.csproj|All Files (*.*)|*.*"
            };
            if (ofd.ShowDialog() == true)
            {
                ProjectPathText.Text = ofd.FileName;
                KeywordBox.Text = string.Empty;
                FileFilter.SelectedIndex = 0;
            }
        }

        private void Close_Click(object sender, RoutedEventArgs e) => Close();

        private void SeverityIconOnlyCheck_Checked(object sender, RoutedEventArgs e)
        {
            try { _showSeverityText = false; ToggleSeverityTextColumn(); } catch { }
        }
        private void SeverityIconOnlyCheck_Unchecked(object sender, RoutedEventArgs e)
        {
            try { _showSeverityText = true; ToggleSeverityTextColumn(); } catch { }
        }
        private void ToggleSeverityTextColumn()
        {
            try
            {
                // 使用命名列切换可见性
                SeverityTextColumn.Visibility = _showSeverityText ? Visibility.Visible : Visibility.Collapsed;
            }
            catch { }
        }

        private void DiagnosticsGrid_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            try
            {
                if (DiagnosticsGrid.SelectedItem is DiagRow row)
                {
                    NavigateToRow(row);
                }
            }
            catch (Exception ex)
            {
                NavigateStatusText.Text = $"定位失败: {ex.Message}";
            }
        }

        private void CopySelectedMenu_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                if (DiagnosticsGrid?.SelectedItems?.Count > 0)
                {
                    var lines = new List<string>();
                    foreach (var item in DiagnosticsGrid.SelectedItems)
                    {
                        if (item is DiagRow row)
                        {
                            lines.Add($"[{row.Severity}] {row.File}:{row.Line}:{row.Column} {row.Id} {row.Message}");
                        }
                    }
                    if (lines.Count > 0)
                    {
                        Clipboard.SetText(string.Join(Environment.NewLine, lines));
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"复制失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private void DiagnosticsGrid_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.C && (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
            {
                if (DiagnosticsGrid.SelectedItems?.Count > 1)
                {
                    var list = new List<string>();
                    foreach (var item in DiagnosticsGrid.SelectedItems)
                    {
                        if (item is DiagRow r)
                            list.Add($"[{r.Severity}] {r.File}:{r.Line}:{r.Column} {r.Id} {r.Message}");
                    }
                    if (list.Count > 0) Clipboard.SetText(string.Join(Environment.NewLine, list));
                }
                else if (DiagnosticsGrid.SelectedItem is DiagRow row)
                {
                    var text = $"[{row.Severity}] {row.File}:{row.Line}:{row.Column} {row.Id} {row.Message}";
                    Clipboard.SetText(text);
                }
            }
        }

        private void NavigateToRow(DiagRow row)
        {
            // 解析路径并尝试打开
            var file = row.File;
            if (!System.IO.Path.IsPathRooted(file))
            {
                var proj = ProjectPathText.Text?.Trim();
                var root = string.IsNullOrWhiteSpace(proj) ? Directory.GetCurrentDirectory() : System.IO.Path.GetDirectoryName(proj)!;
                var abs = System.IO.Path.Combine(root, file);
                file = System.IO.Path.GetFullPath(abs);
            }
            if (File.Exists(file))
            {
                var main = Application.Current?.MainWindow as MainWindow;
                main?.DocumentEditorControl?.OpenAndNavigateAsync(file, row.Line, row.Column);
                main?.Activate();
                NavigateStatusText.Text = $"已定位到 {System.IO.Path.GetFileName(file)}:{row.Line}:{row.Column}";
            }
        }

        private void FileFilterSearchBox_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
        {
            try { ApplyFileFilterSearch(); } catch { }
        }
        private void FileFilterSearchBox_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            try
            {
                if (e.Key == Key.Enter)
                {
                    // 回车：若存在第一个匹配项，选中并应用过滤
                    var kw = FileFilterSearchBox.Text?.Trim() ?? string.Empty;
                    if (!string.IsNullOrEmpty(kw))
                    {
                        // Items[0] 为“全部文件”，从 1 起找
                        for (int i = 1; i < FileFilter.Items.Count; i++)
                        {
                            if (FileFilter.Items[i] is System.Windows.Controls.ComboBoxItem it)
                            {
                                var content = it.Content?.ToString() ?? string.Empty;
                                if (content.IndexOf(kw, StringComparison.OrdinalIgnoreCase) >= 0)
                                {
                                    FileFilter.SelectedIndex = i;
                                    ApplyFilters();
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            catch { }
        }

        private void ClearFileFilter_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                FileFilterSearchBox.Text = string.Empty;
                BuildFileFilterItems(_allFiles, GetProjectRootDir());
                FileFilter.SelectedIndex = 0;
                ApplyFilters();
            }
            catch { }
        }


        private void ApplyFileFilterSearch()
        {
            try
            {
                var kw = FileFilterSearchBox.Text?.Trim() ?? string.Empty;
                var root = GetProjectRootDir();
                var list = string.IsNullOrEmpty(kw)
                    ? _allFiles
                    : _allFiles.Where(f => f.IndexOf(kw, StringComparison.OrdinalIgnoreCase) >= 0
                        || Path.GetFileName(f).IndexOf(kw, StringComparison.OrdinalIgnoreCase) >= 0)
                               .ToList();
                BuildFileFilterItems(list, root);
            }
            catch { }
        }

        private void BuildFileFilterItems(List<string> files, string root)
        {
            try
            {
                var prevTag = (FileFilter.SelectedItem as System.Windows.Controls.ComboBoxItem)?.Tag as string;
                FileFilter.Items.Clear();
                FileFilter.Items.Add(new System.Windows.Controls.ComboBoxItem { Content = "全部文件", ToolTip = "全部文件" });
                int selectIndex = 0;
                for (int i = 0; i < files.Count; i++)
                {
                    var f = files[i];
                    var display = BuildFileDisplayLabel(f, root);
                    var item = new System.Windows.Controls.ComboBoxItem { Content = display, Tag = f, ToolTip = f };
                    FileFilter.Items.Add(item);
                    if (!string.IsNullOrEmpty(prevTag) && string.Equals(prevTag, f, StringComparison.OrdinalIgnoreCase))
                        selectIndex = i + 1; // +1 因为 0 是“全部文件”
                }
                FileFilter.SelectedIndex = selectIndex;
            }
            catch { }
        }

        private void KeywordBox_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e) => ApplyFilters();
        private void FileFilter_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) => ApplyFilters();

        private void ApplyFilters()
        {
            try
            {
                IEnumerable<DiagRow> data = _allRows;
                var severity = (SeverityFilter.SelectedItem as System.Windows.Controls.ComboBoxItem)?.Content?.ToString();
                if (!string.IsNullOrEmpty(severity) && severity != "全部")
                    data = data.Where(r => r.Severity.Equals(severity, StringComparison.OrdinalIgnoreCase));

                var selItem = FileFilter.SelectedItem as System.Windows.Controls.ComboBoxItem;
                var fileTag = selItem?.Tag as string;
                var fileSel = selItem?.Content?.ToString();
                if (!string.IsNullOrEmpty(fileTag))
                    data = data.Where(r => r.File.Equals(fileTag, StringComparison.OrdinalIgnoreCase));
                else if (!string.IsNullOrEmpty(fileSel) && fileSel != "全部文件")
                    data = data.Where(r => r.File.EndsWith(fileSel, StringComparison.OrdinalIgnoreCase));

                var kw = KeywordBox.Text?.Trim();
                if (!string.IsNullOrEmpty(kw))
                    data = data.Where(r => (r.Id?.IndexOf(kw, StringComparison.OrdinalIgnoreCase) ?? -1) >= 0
                        || (r.Message?.IndexOf(kw, StringComparison.OrdinalIgnoreCase) ?? -1) >= 0
                        || (r.File?.IndexOf(kw, StringComparison.OrdinalIgnoreCase) ?? -1) >= 0);

                var list = data.ToList();
                DiagnosticsGrid.ItemsSource = list;
                SummaryText.Text = $"合计: {list.Count} 条";
            }
            catch { }
        }

        private void RebuildFileFilterItems(List<DiagRow> rows)
        {
            try
            {
                var files = rows.Select(r => r.File).Distinct(StringComparer.OrdinalIgnoreCase)
                                .OrderBy(s => s, StringComparer.OrdinalIgnoreCase).ToList();
                _allFiles = files;
                BuildFileFilterItems(files, GetProjectRootDir());
            }
            catch { }
        }


        /// <summary>
        /// 将后端/工具返回的严重级统一映射为中文（错误/警告/信息）。
        /// </summary>
        private static string MapSeverityToChinese(string sev)
        {
            if (string.IsNullOrWhiteSpace(sev)) return string.Empty;
            var s = sev.Trim();
            if (s == "错误" || s == "警告" || s == "信息") return s;
            var si = s.ToLowerInvariant();
            return si switch
            {
                // 错误类
                "error" => "错误",
                "fatal" => "错误",
                "critical" => "错误",
                // 警告类
                "warning" => "警告",
                "warn" => "警告",
                // 信息/提示类
                "info" => "信息",
                "information" => "信息",
                "suggestion" => "信息",
                "hint" => "信息",
                "hidden" => "信息",
                "none" => "信息",
                "message" => "信息",
                "debug" => "信息",
                "trace" => "信息",
                _ => s
            };
        }

        /// <summary>
        /// 获取项目根目录（基于项目文件路径文本框），若未指定则使用当前目录。
        /// </summary>
        private string GetProjectRootDir()
        {
            var proj = ProjectPathText.Text?.Trim();
            return string.IsNullOrWhiteSpace(proj)
                ? Directory.GetCurrentDirectory()
                : System.IO.Path.GetDirectoryName(proj)!;
        }

        /// <summary>
        /// 构建“文件名（相对目录）”形式的显示标签。
        /// </summary>
        private string BuildFileDisplayLabel(string filePath, string projectRoot)
        {
            try
            {
                var name = System.IO.Path.GetFileName(filePath);
                var abs = ResolveToAbsolutePath(filePath);
                var rel = MakeRelativePath(projectRoot, abs);
                var relDir = System.IO.Path.GetDirectoryName(rel) ?? string.Empty;
                if (string.IsNullOrWhiteSpace(relDir) || relDir == ".")
                {
                    return name;
                }
                return $"{name}（{relDir}）"; // 使用中文括号
            }
            catch
            {
                // 回退：仅文件名
                return System.IO.Path.GetFileName(filePath);
            }
        }

        /// <summary>
        /// 生成从 root 到 path 的相对路径；失败时返回原路径。
        /// </summary>
        private static string MakeRelativePath(string root, string path)
        {
            try
            {
                // .NET 提供的方法
                var rel = System.IO.Path.GetRelativePath(root, path);
                return string.IsNullOrWhiteSpace(rel) ? path : rel;
            }
            catch
            {
                try
                {
                    // Uri 回退方案
                    var rootUri = new Uri(EnsureTrailingSeparator(root));
                    var pathUri = new Uri(path);
                    if (rootUri.IsBaseOf(pathUri))
                    {
                        var relative = Uri.UnescapeDataString(rootUri.MakeRelativeUri(pathUri).ToString());
                        return relative.Replace('/', System.IO.Path.DirectorySeparatorChar);
                    }
                }
                catch { }
                return path;
            }
        }

        private static string EnsureTrailingSeparator(string p)
        {
            if (string.IsNullOrEmpty(p)) return p;
            var sep = System.IO.Path.DirectorySeparatorChar;
            return p.EndsWith(sep) ? p : p + sep;
        }



        private sealed class DiagRow
        {
            public string Severity { get; set; } = string.Empty;
            public string Id { get; set; } = string.Empty;
            public string Message { get; set; } = string.Empty;
            public string File { get; set; } = string.Empty;
            public int Line { get; set; }
            public int Column { get; set; }
        }

        private void OpenContainingFolderMenu_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                if (DiagnosticsGrid.SelectedItem is DiagRow row)
                {
                    var file = ResolveToAbsolutePath(row.File);
                    var dir = System.IO.Path.GetDirectoryName(file);
                    if (!string.IsNullOrWhiteSpace(dir) && Directory.Exists(dir))
                    {
                        Process.Start(new ProcessStartInfo
                        {
                            FileName = dir,
                            UseShellExecute = true,
                            Verb = "open"
                        });
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"打开目录失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private void OpenFolderInTerminalMenu_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                if (DiagnosticsGrid.SelectedItem is DiagRow row)
                {
                    var file = ResolveToAbsolutePath(row.File);
                    var dir = System.IO.Path.GetDirectoryName(file);
                    if (!string.IsNullOrWhiteSpace(dir) && Directory.Exists(dir))
                    {
                        // 在 Windows 上尝试打开 Windows Terminal，如果不可用则退回 cmd
                        var wt = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft", "Windows Terminal", "wt.exe");
                        if (File.Exists(wt))
                        {
                            Process.Start(new ProcessStartInfo
                            {
                                FileName = wt,
                                Arguments = $"-d \"{dir}\"",
                                UseShellExecute = false,
                            });
                        }
                        else
                        {
                            Process.Start(new ProcessStartInfo
                            {
                                FileName = "cmd.exe",
                                Arguments = $"/K cd /d \"{dir}\"",
                                UseShellExecute = false,
                            });
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"打开终端失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private string ResolveToAbsolutePath(string file)
        {
            if (System.IO.Path.IsPathRooted(file)) return file;
            var proj = ProjectPathText.Text?.Trim();
            var root = string.IsNullOrWhiteSpace(proj) ? Directory.GetCurrentDirectory() : System.IO.Path.GetDirectoryName(proj)!;
            var abs = System.IO.Path.Combine(root, file);
            return System.IO.Path.GetFullPath(abs);
        }
    }
}

